home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / ole2book.zip / CHAP06.ZIP / CHAP06 / EDATAOBJ / IDATAOBJ.CPP < prev    next >
C/C++ Source or Header  |  1993-04-21  |  12KB  |  477 lines

  1. /*
  2.  * IDATAOBJ.CPP
  3.  * Data Object for Chapter 6
  4.  *
  5.  * Implementation of the IDataObject interface for CDataObject.
  6.  *
  7.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  8.  *
  9.  * Kraig Brockschmidt, Software Design Engineer
  10.  * Microsoft Systems Developer Relations
  11.  *
  12.  * Internet  :  kraigb@microsoft.com
  13.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  14.  */
  15.  
  16.  
  17. #include "dataobj.h"
  18.  
  19.  
  20.  
  21. /*
  22.  * CImpIDataObject::CImpIDataObject
  23.  * CImpIDataObject::~CImpIDataObject
  24.  *
  25.  * Parameters (Constructor):
  26.  *  pObj            LPVOID of the object we're in.
  27.  *  punkOuter       LPUNKNOWN to which we delegate.
  28.  */
  29.  
  30. CImpIDataObject::CImpIDataObject(LPVOID pObj, LPUNKNOWN punkOuter)
  31.     {
  32.     m_cRef=0;
  33.     m_pObj=pObj;
  34.     m_punkOuter=punkOuter;
  35.     return;
  36.     }
  37.  
  38. CImpIDataObject::~CImpIDataObject(void)
  39.     {
  40.     return;
  41.     }
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48. /*
  49.  * CImpIDataObject::QueryInterface
  50.  * CImpIDataObject::AddRef
  51.  * CImpIDataObject::Release
  52.  *
  53.  * Purpose:
  54.  *  IUnknown members for CImpIDataObject object.
  55.  */
  56.  
  57. STDMETHODIMP CImpIDataObject::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  58.     {
  59.     return m_punkOuter->QueryInterface(riid, ppv);
  60.     }
  61.  
  62.  
  63. STDMETHODIMP_(ULONG) CImpIDataObject::AddRef(void)
  64.     {
  65.     ++m_cRef;
  66.     return m_punkOuter->AddRef();
  67.     }
  68.  
  69. STDMETHODIMP_(ULONG) CImpIDataObject::Release(void)
  70.     {
  71.     --m_cRef;
  72.     return m_punkOuter->Release();
  73.     }
  74.  
  75.  
  76.  
  77.  
  78.  
  79. /*
  80.  * CImpIDataObject::GetData
  81.  *
  82.  * Purpose:
  83.  *  Retrieves data described by a specific FormatEtc into a StgMedium
  84.  *  allocated by this function.  Used like GetClipboardData.
  85.  *
  86.  * Parameters:
  87.  *  pFE             LPFORMATETC describing the desired data.
  88.  *  pSTM            LPSTGMEDIUM in which to return the data.
  89.  *
  90.  * Return Value:
  91.  *  HRESULT         NOERROR on success, error code otherwise.
  92.  */
  93.  
  94. STDMETHODIMP CImpIDataObject::GetData(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
  95.     {
  96.     LPCDataObject   pObj=(LPCDataObject)m_pObj;
  97.     UINT            cf=pFE->cfFormat;
  98.  
  99.     /*
  100.      * This function is just cycling through each format you support
  101.      * and finding a match with the requested one, rendering that
  102.      * data, then returning NOERROR, otherwise returning either
  103.      * DATA_E_FORMATETC or STG_E_MEDIUMFULL on error.
  104.      */
  105.  
  106.     //Check the aspects we support.
  107.     if (!(DVASPECT_CONTENT & pFE->dwAspect))
  108.         return ResultFromScode(DATA_E_FORMATETC);
  109.  
  110.     switch (cf)
  111.         {
  112.         case CF_METAFILEPICT:
  113.             if (!(TYMED_MFPICT & pFE->tymed))
  114.                 break;
  115.  
  116.             return pObj->RenderMetafilePict(pSTM);
  117.  
  118.         case CF_BITMAP:
  119.             if (!(TYMED_GDI & pFE->tymed))
  120.                 break;
  121.  
  122.             return pObj->RenderBitmap(pSTM);
  123.  
  124.         case CF_TEXT:
  125.             if (!(TYMED_HGLOBAL & pFE->tymed))
  126.                 break;
  127.  
  128.             return pObj->RenderText(pSTM);
  129.  
  130.         default:
  131.             break;
  132.         }
  133.  
  134.     return ResultFromScode(DATA_E_FORMATETC);
  135.     }
  136.  
  137.  
  138.  
  139.  
  140. /*
  141.  * CImpIDataObject::GetDataHere
  142.  *
  143.  * Purpose:
  144.  *  Renders the specific FormatEtc into caller-allocated medium
  145.  *  provided in pSTM.
  146.  *
  147.  * Parameters:
  148.  *  pFE             LPFORMATETC describing the desired data.
  149.  *  pSTM            LPSTGMEDIUM providing the medium into which
  150.  *                  wer render the data.
  151.  *
  152.  * Return Value:
  153.  *  HRESULT         NOERROR on success, error code otherwise.
  154.  */
  155.  
  156. STDMETHODIMP CImpIDataObject::GetDataHere(LPFORMATETC pFE, LPSTGMEDIUM pSTM)
  157.     {
  158.     //We don't implement this now.
  159.     return ResultFromScode(E_NOTIMPL);
  160.     }
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167. /*
  168.  * CImpIDataObject::QueryGetData
  169.  *
  170.  * Purpose:
  171.  *  Tests if a call to ::GetData with this FormatEtc will provide
  172.  *  any rendering; used like IsClipboardFormatAvailable.
  173.  *
  174.  * Parameters:
  175.  *  pFE             LPFORMATETC describing the desired data.
  176.  *
  177.  * Return Value:
  178.  *  HRESULT         NOERROR on success, error code otherwise.
  179.  */
  180.  
  181. STDMETHODIMP CImpIDataObject::QueryGetData(LPFORMATETC pFE)
  182.     {
  183.     LPCDataObject   pObj=(LPCDataObject)m_pObj;
  184.     UINT            cf=pFE->cfFormat;
  185.     BOOL            fRet=FALSE;
  186.  
  187.     /*
  188.      * This function is just cycling through each format you support
  189.      * and finding a match with the requested one, returning NOERROR
  190.      * if you do have it, S_FALSE if you don't.
  191.      */
  192.  
  193.     //Check the aspects we support.
  194.     if (!(DVASPECT_CONTENT & pFE->dwAspect))
  195.         return ResultFromScode(S_FALSE);
  196.  
  197.     switch (cf)
  198.         {
  199.         case CF_METAFILEPICT:
  200.             fRet=(BOOL)(pFE->tymed & TYMED_MFPICT);
  201.             break;
  202.  
  203.         case CF_BITMAP:
  204.             fRet=(BOOL)(pFE->tymed & TYMED_GDI);
  205.             break;
  206.  
  207.         case CF_TEXT:
  208.             fRet=(BOOL)(pFE->tymed & TYMED_HGLOBAL);
  209.             break;
  210.  
  211.         default:
  212.             fRet=FALSE;
  213.             break;
  214.         }
  215.  
  216.     return fRet ? NOERROR : ResultFromScode(S_FALSE);
  217.     }
  218.  
  219.  
  220.  
  221.  
  222.  
  223.  
  224. /*
  225.  * CImpIDataObject::GetCanonicalFormatEtc
  226.  *
  227.  * Purpose:
  228.  *  Provides the caller with an equivalent FormatEtc to the one
  229.  *  provided when different FormatEtcs will produce exactly the
  230.  *  same renderings.
  231.  *
  232.  * Parameters:
  233.  *  pFEIn            LPFORMATETC of the first description.
  234.  *  pFEOut           LPFORMATETC of the equal description.
  235.  *
  236.  * Return Value:
  237.  *  HRESULT         NOERROR on success, error code otherwise.
  238.  */
  239.  
  240. STDMETHODIMP CImpIDataObject::GetCanonicalFormatEtc(LPFORMATETC pFEIn
  241.     , LPFORMATETC pFEOut)
  242.     {
  243.     /*
  244.      *  1.  If you support an equivalent of pFEIn, return it in pFEOut.
  245.      *  2.  Return NOERROR if you filled pFEOut with anything, otherwise
  246.      *      return DATA_S_SAMEFORMATETC.  If you say that all renderings
  247.      *      are identical, return DATA_S_SAMEFORMATETC.
  248.      */
  249.  
  250.     return ResultFromScode(DATA_S_SAMEFORMATETC);
  251.     }
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258. /*
  259.  * CImpIDataObject::SetData
  260.  *
  261.  * Purpose:
  262.  *  Places data described by a FormatEtc and living in a StgMedium
  263.  *  into the object.  The object may be responsible to clean up the
  264.  *  StgMedium before exiting.
  265.  *
  266.  * Parameters:
  267.  *  pFE             LPFORMATETC describing the data to set.
  268.  *  pSTM            LPSTGMEDIUM containing the data.
  269.  *  fRelease        BOOL indicating if this function is responsible for
  270.  *                  freeing the data.
  271.  *
  272.  * Return Value:
  273.  *  HRESULT         NOERROR on success, error code otherwise.
  274.  */
  275.  
  276. STDMETHODIMP CImpIDataObject::SetData(LPFORMATETC pFE, STGMEDIUM FAR *pSTM
  277.     , BOOL fRelease)
  278.     {
  279.     //We don't handle SetDatas here.
  280.     return ResultFromScode(DATA_E_FORMATETC);
  281.     }
  282.  
  283.  
  284.  
  285.  
  286.  
  287.  
  288. /*
  289.  * CImpIDataObject::EnumFormatEtc
  290.  *
  291.  * Purpose:
  292.  *  Returns an IEnumFORMATETC object through which the caller can iterate
  293.  *  to learn about all the data formats this object can provide through
  294.  *  either ::GetData[Here] or ::SetData.
  295.  *
  296.  * Parameters:
  297.  *  dwDir           DWORD describing a data direction, either DATADIR_SET
  298.  *                  or DATADIR_GET.
  299.  *  ppEnum          LPENUMFORMATETC FAR * in which to return the pointer
  300.  *                  to the enumerator.
  301.  *
  302.  * Return Value:
  303.  *  HRESULT         NOERROR on success, error code otherwise.
  304.  */
  305.  
  306. STDMETHODIMP CImpIDataObject::EnumFormatEtc(DWORD dwDir
  307.     , LPENUMFORMATETC FAR *ppEnum)
  308.     {
  309.     LPCDataObject   pObj=(LPCDataObject)m_pObj;
  310.  
  311.     /*
  312.      * We only support ::GetData in this object so we return NULL for
  313.      * DATADIR_SET.  Otherwise we instantiate one of our CEnumFormatEtc
  314.      * objects which has all the appropriate functions; we only need to
  315.      * tell it where our arrays live.
  316.      *
  317.      * The m_punkOuter passed to the enumerator allows the enumerator
  318.      * to AddRef and Release our controlling unknown as it receives
  319.      * reference counting calls.  By calling AddRef itself, it can
  320.      * insure that the object that holds the data context will stick
  321.      * around as long as the enumerator itself is around.  Otherwise
  322.      * it could be enumerating through bogus data.
  323.      */
  324.  
  325.     switch (dwDir)
  326.         {
  327.         case DATADIR_GET:
  328.             *ppEnum=(LPENUMFORMATETC)new CEnumFormatEtc(m_punkOuter
  329.                 , pObj->m_cfeGet, pObj->m_rgfeGet);
  330.              break;
  331.  
  332.         case DATADIR_SET:
  333.             *ppEnum=NULL;
  334.             break;
  335.  
  336.         default:
  337.             *ppEnum=NULL;
  338.             break;
  339.         }
  340.  
  341.     if (NULL==*ppEnum)
  342.         return ResultFromScode(E_FAIL);
  343.     else
  344.         (*ppEnum)->AddRef();
  345.  
  346.     return NOERROR;
  347.     }
  348.  
  349.  
  350.  
  351.  
  352.  
  353. /*
  354.  * CImpIDataObject::DAdvise
  355.  *
  356.  * Purpose:
  357.  *  Provides the data object with an IAdviseSink object that we are
  358.  *  responsible to notify when the data changes.
  359.  *
  360.  * Parameters:
  361.  *  ppFE            LPFORMATETC
  362.  *  dwFlags         DWORD carrying flags indicating how the advise sink
  363.  *                  wants to be treated.
  364.  *  pIAdviseSink    LPADVISESINK to the object to notify on data changes.
  365.  *  pdwConn         LPDWORD into which we store a DWORD key identifying
  366.  *                  the advise connection.
  367.  *
  368.  * Return Value:
  369.  *  HRESULT         NOERROR on success, error code otherwise.
  370.  */
  371.  
  372. STDMETHODIMP CImpIDataObject::DAdvise(LPFORMATETC pFE, DWORD dwFlags
  373.     , LPADVISESINK pIAdviseSink, LPDWORD pdwConn)
  374.     {
  375.     LPCDataObject   pObj=(LPCDataObject)m_pObj;
  376.     HRESULT         hr;
  377.  
  378.     /*
  379.      *  1.  If you've already created an advise holder for this object,
  380.      *      skip to step 3.  If there are multiple clients connected the
  381.      *      one advise holder takes care of it when we call it's Advise.
  382.      *  2.  Create and save an advise holder interface using
  383.      *      CreateDataAdviseHolder.  Return E_OUTOFMEMORY on failure.
  384.      *  3.  Call the IDataAdviseHolder::Advise member passing to it the
  385.      *      advise sink and pdwConn.
  386.      *  4.  Return the HRESULT from step 3;
  387.      */
  388.  
  389.     if (NULL==pObj->m_pIDataAdviseHolder)
  390.         {
  391.         hr=CreateDataAdviseHolder(&pObj->m_pIDataAdviseHolder);
  392.  
  393.         if (FAILED(hr))
  394.             return ResultFromScode(E_OUTOFMEMORY);
  395.         }
  396.  
  397.     hr=pObj->m_pIDataAdviseHolder->Advise((LPDATAOBJECT)this, pFE
  398.         , dwFlags, pIAdviseSink, pdwConn);
  399.  
  400.     return hr;
  401.     }
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408. /*
  409.  * CImpIDataObject::DUnadvise
  410.  *
  411.  * Purpose:
  412.  *  Turns off advising previously set up with ::Advise.
  413.  *
  414.  * Parameters:
  415.  *  dwConn          DWORD connection key returned from ::Advise.
  416.  *
  417.  * Return Value:
  418.  *  HRESULT         NOERROR on success, error code otherwise.
  419.  */
  420.  
  421. STDMETHODIMP CImpIDataObject::DUnadvise(DWORD dwConn)
  422.     {
  423.     LPCDataObject   pObj=(LPCDataObject)m_pObj;
  424.     HRESULT         hr;
  425.  
  426.     /*
  427.      *  1.  If you have stored and advise holder from IDataObject::Advise
  428.      *      then pass dwConn to it's Unadvise and return the HRESULT from
  429.      *      that function.
  430.      *  2.  If you have no advise holder, return E_FAIL;
  431.      */
  432.  
  433.     if (NULL==pObj->m_pIDataAdviseHolder)
  434.         return ResultFromScode(E_FAIL);
  435.  
  436.     hr=pObj->m_pIDataAdviseHolder->Unadvise(dwConn);
  437.  
  438.     return hr;
  439.     }
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446. /*
  447.  * CImpIDataObject::EnumDAdvise
  448.  *
  449.  * Purpose:
  450.  *  Returns an enumerator object through which the caller can find all
  451.  *  the agents currently receiving advises on this data object.
  452.  *
  453.  * Parameters:
  454.  *  ppEnum          LPENUMSTATDATA FAR * in which to return the enumerator.
  455.  *
  456.  * Return Value:
  457.  *  HRESULT         NOERROR on success, error code otherwise.
  458.  */
  459.  
  460. STDMETHODIMP CImpIDataObject::EnumDAdvise(LPENUMSTATDATA FAR *ppEnum)
  461.     {
  462.     LPCDataObject   pObj=(LPCDataObject)m_pObj;
  463.     HRESULT         hr;
  464.  
  465.     /*
  466.      *  1.  If you have a stored IDataAdviseHolder, pass this request on
  467.      *      to its EnumAdvise and return the HRESULT from that function.
  468.      *  2.  Otherwise return E_FAIL.
  469.      */
  470.  
  471.     if (NULL==pObj->m_pIDataAdviseHolder)
  472.         return ResultFromScode(E_FAIL);
  473.  
  474.     hr=pObj->m_pIDataAdviseHolder->EnumAdvise(ppEnum);
  475.     return hr;
  476.     }
  477.